package com.face.client.model;

import com.arcsoft.AFR_FSDK_FACEMODEL;
import com.arcsoft.ASVLOFFSCREEN;
import com.arcsoft.FaceInfo;
import com.arcsoft.MRECT;
import com.arcsoft.ftrace.AFT_FSDKLibrary;
import com.arcsoft.ftrace.AFT_FSDK_FACERES;
import com.arcsoft.ftrace._AFT_FSDK_OrientPriority;
import com.face.Const;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import com.util.ImageUtils;
import com.util.SDKUtils;

public class AFTEngine implements FaceCheck, Engine {

    private final int size = 40 * 1024 * 1024;
    private final int nScale = 16;
    private final int faceNum = 1;

    private static ThreadLocal<Pointer> pEngine = new ThreadLocal<>();
    private static ThreadLocal<Pointer> pMemory = new ThreadLocal<>();

    @Override
    public Pointer get() {
        return get(pEngine);
    }


    @Override
    public Pointer init() {
        System.out.println("初始化FT引擎");
        PointerByReference phFTEngine = new PointerByReference();
        Pointer memory = SDKUtils.createMem(size);
        NativeLong ret = AFT_FSDKLibrary.INSTANCE.AFT_FSDK_InitialFaceEngine(Const.APPID, Const.FT_SDKKEY, memory,
                size, phFTEngine, _AFT_FSDK_OrientPriority.AFT_FSDK_OPF_0_HIGHER_EXT, nScale, faceNum);
        if (ifError(memory, ret)) {
            System.err.println("FT引擎初始化异常");
        }
        Pointer engine = phFTEngine.getValue();
        pEngine.set(engine);
        pMemory.set(memory);
        return engine;
    }

    @Override
    public void destroy() {
        destroy(pEngine, pMemory);
    }

    @Override
    public void release(Pointer engine) {
        AFT_FSDKLibrary.INSTANCE.AFT_FSDK_UninitialFaceEngine(engine);
    }


    @Override
    public Pointer getFaceRes(ASVLOFFSCREEN inputImg) {
        PointerByReference ppFaceRes = new PointerByReference();
        NativeLong ret = AFT_FSDKLibrary.INSTANCE.AFT_FSDK_FaceFeatureDetect(get(), inputImg, ppFaceRes);
        if (ret.longValue() != 0) {
            throw new RuntimeException(String.format("AFT_FSDK_StillImageFaceDetection ret 0x%x", ret.longValue()));
        }
        return ppFaceRes.getValue();
    }

    @Override
    public FaceInfo[] getFaceInfo(ASVLOFFSCREEN asvloffscreen) {
        Pointer ppFaceRes = getFaceRes(asvloffscreen);
        AFT_FSDK_FACERES faceRes = new AFT_FSDK_FACERES(ppFaceRes);
        int num = faceRes.nFace;
        FaceInfo[] faceInfo = new FaceInfo[faceRes.nFace];
        for (int i = 0; i < num; i++) {
            MRECT rect = new MRECT(
                    new Pointer(Pointer.nativeValue(faceRes.rcFace.getPointer()) + faceRes.rcFace.size() * i));
            faceInfo[i] = new FaceInfo();
            faceInfo[i].left = rect.left;
            faceInfo[i].top = rect.top;
            faceInfo[i].right = rect.right;
            faceInfo[i].bottom = rect.bottom;
        }
        return faceInfo;
    }

    public static void main(String[] args) {
        String path = args[0];
        AFTEngine aftEngine = new AFTEngine();
        ASVLOFFSCREEN screen = ImageUtils.loadImage(path);
        FaceInfo[] faceInfos = aftEngine.getFaceInfo(screen);
        AFREngine afrEngine = new AFREngine();
        AFR_FSDK_FACEMODEL model = afrEngine.extractFRFeature(screen, faceInfos[0]);

    }
}
